﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Commands
{
    internal class SystemIdleInformator
    {
        /// <summary>
        /// Get time in which user have no activity.
        /// </summary>
        public static TimeSpan? GetInactiveTime()
        {
            LASTINPUTINFO info = new LASTINPUTINFO();
            info.cbSize = (uint)Marshal.SizeOf(info);
            if (GetLastInputInfo(ref info))
                return TimeSpan.FromMilliseconds(Environment.TickCount - info.dwTime);
            else
                return null;
        }

        /// <summary>
        /// Simulate user activity. By sending press of enter key.
        /// </summary>
        public static void SimulateUserActivity()
        {
            KEYBOARDINPUT[] inputs;
            uint retVal;
            int error;
            inputs = new KEYBOARDINPUT[2];
            inputs[0].type = inputs[1].type = INPUT_KEYBOARD;
            inputs[0].wVk = inputs[1].wVk = (int)KeyCode.ENTER;
            inputs[1].dwFlags = KEYEVENTF_KEYUP;
            retVal = SendInput(2, inputs, 0x001C);
            if (retVal != 2)
            {
                error = Marshal.GetLastWin32Error();
                throw new Exception(string.Format("SendInput() returned {0}.", error));
            }
        }
        
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);

/// <summary>
/// simulate key press
/// </summary>
/// <param name="keyCode"></param>
public static void SendKeyPress(KeyCode keyCode)
{
    INPUT input = new INPUT {
        Type = 1
    };
    input.Data.Keyboard = new KEYBDINPUT() {
        Vk = (ushort)keyCode,
        Scan = 0,
        Flags = 0,
        Time = 0,
        ExtraInfo = IntPtr.Zero,
    };

    INPUT input2 = new INPUT {
        Type = 1
    };
    input2.Data.Keyboard = new KEYBDINPUT() {
        Vk = (ushort)keyCode,
        Scan = 0,
        Flags = 2,
        Time = 0,
        ExtraInfo = IntPtr.Zero
    };
    INPUT[] inputs = new INPUT[] { input, input2 };
    if (SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))) == 0)
        throw new Exception();            
}

        [StructLayout(LayoutKind.Sequential)]
        private struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }

        [DllImport("user32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        [DllImport("coredll.dll", SetLastError = true)]
        private static extern uint SendInput(uint cInputs, /* [MarshalAs(UnmanagedType.LPArray)] */ 
            KEYBOARDINPUT[] inputs, int cbSize);

        private struct KEYBOARDINPUT
        {
            public uint type;
            public ushort wVk;
            ushort wScan;
            public uint dwFlags;
            uint time;
            uint dwExtraInfo;
            uint unused1;
            uint unused2;
        }

        private enum KeyCode : ushort
        {
            /// <summary>
            /// Return key
            /// </summary>
            ENTER = 13
            //private const ushort VK_TAB = 0x0009;
            //private const ushort VK_SHIFT = 0x0010;
            //private const ushort VK_CTRL = 0x0011;
        }

        private const uint INPUT_KEYBOARD = 1;
        private const uint KEYEVENTF_KEYUP = 2;
}